#ifndef _SPI_FLASH_OP_H_
#define _SPI_FLASH_OP_H_

#include "stm32f4xx.h"

// 区域	起始地址	结束地址	长度（Sector 数）
// OTA	0x000000	0x0BFFFF	768 KB (192 × 4 KB)
// LFS2	0x0C0000	0x1FFFFF	1280 KB (320 × 4 KB)

/* W25Q16JVSS 2 MB 划分 */
#define FLASH_OTA_SIZE_KB  768
#define FLASH_LFS2_SIZE_KB 1280

#define FLASH_OTA_START 0x000000
#define FLASH_OTA_END   0x0BFFFF // 768 KB 边界

#define FLASH_LFS2_START 0x0C0000 // 紧接 OTA 之后
#define FLASH_LFS2_END   0x1FFFFF // 芯片末地址

#define CMD_WRITE_ENABLE  0x06
#define CMD_WRITE_DISABLE 0x04
#define CMD_READ_STATUS   0x05
#define CMD_PAGE_PROGRAM  0x02
#define CMD_SECTOR_ERASE  0x20 // 4 KB
#define CMD_READ_DATA     0x03
#define CMD_JEDEC_ID      0x9F
/* ---------- GPIO 宏 ---------- */
#define RCC_AHB1ENR (*(volatile uint32_t *)0x40023830) // RCC_AHB1ENR
#define GPIOE_MODER (*(volatile uint32_t *)0x40021000) // PE
#define GPIOE_ODR   (*(volatile uint32_t *)0x40021014) // 输出数据
#define GPIOE_IDR   (*(volatile uint32_t *)0x40021010) // 输入数据

#define SoftSPI_FLASH_CS_H()   (GPIOE_ODR |= (1 << 2))
#define SoftSPI_FLASH_CS_L()   (GPIOE_ODR &= ~(1 << 2))
#define SoftSPI_FLASH_SCK_H()  (GPIOE_ODR |= (1 << 3))
#define SoftSPI_FLASH_SCK_L()  (GPIOE_ODR &= ~(1 << 3))
#define SoftSPI_FLASH_MOSI_H() (GPIOE_ODR |= (1 << 5))
#define SoftSPI_FLASH_MOSI_L() (GPIOE_ODR &= ~(1 << 5))
#define SoftSPI_FLASH_MISO     ((GPIOE_IDR >> 4) & 1)

/* ---------- 初始化 ---------- */
void SoftSPIFlash_Init(void);
/* ---------- 收发 1 Byte ---------- */
uint8_t SoftSPIFlash_RW(uint8_t out);
/* ---------- 读 Flash ID 示例 ---------- */
uint32_t SoftSPIFlash_ReadJEDEC(void);
static int SoftSPIFlash_WaitBusy(void);
uint32_t SoftSPIFlash_ReadID(void);
void SoftSPIFlash_PageWrite(uint32_t addr, const uint8_t *buf, uint16_t len);
void SoftSPIFlash_Read(uint32_t addr, uint8_t *buf, uint32_t len);

void SoftSPIFlash_SectorErase(uint32_t addr);
void SoftSPIFlash_test(void);

int OTA_Flash_EraseAndVerify(void);
// int SPIFlash_Write256_InBound(uint32_t addr, const uint8_t *src, uint16_t len);
int SPIFlash_Write1K_InBound(uint32_t addr,
                             const uint8_t *src,
                             uint8_t *wrote_data,
                             uint16_t len);
#endif // ! _SPI_FLASH__OP_H
